#include "HTTPRequest.h"
#include "HTTPResponse.h"

using namespace std;

CHTTPRequest::CHTTPRequest(Client *aClient)
{
	mClient = aClient;
	mResponse = nullptr;
	//cout << "CHTTPRequest constructed" << endl;
}


CHTTPRequest::~CHTTPRequest(void)
{

}

bool CHTTPRequest::ProcessHeader()
{
	// Read from socket until we get a blank line with \r\n on it.

	string Buffer;
	string TempBuffer;
	int Length = Buffer.length();

	while((Buffer.length() < 4) || ((Buffer.find("\r\n\r\n") == string::npos) && (Buffer.find("\n\n") == string::npos)))
	{
		TempBuffer = mClient->Receive();
		if(TempBuffer == "-1")
		{
			if(mClient->mSocket->GetSocketError() != 6 && mClient->mSocket->GetSocketError() != 0)
			{
				cout << "Socket Error: " << mClient->mSocket->GetSocketError() << endl;
				return false;
			}
		}
		else if(TempBuffer == "-2")
		{
			cout << "Receive returned 0" << endl;
			return false;
		}
		else
		{
			Buffer += TempBuffer;
		}
	}

	if(Buffer.length() < 1)
	{
		return false;
	}

	vector<string> RequestLines;
	int Offset = 0;
	size_t Pos;
	Pos = Buffer.find("\r\n");
	if(Pos == string::npos)
	{
		//ERROR Malformed Request
		return false;
	}

	string Line = Buffer.substr(0, Pos);
	Offset = Pos;
	// HACK This is a mess
	// This removes ".." from resource, so that hopefully we don't escape out of our original directory
	/*string find = "..";
	string replace = "";
	size_t j;
	for ( ; (j = Line.find(find)) != string::npos ; ) {
		Line.replace( j, find.length(), "" );
	}*/
	mRequestInfo = HTTPRequestInfo(Line);

	if(!mRequestInfo.IsValid())
	{
		//ERROR Malformed Request
		return false;
	}

	while(Buffer.length() > 0)
	{
		Pos = Buffer.find("\r\n", Offset+1);
		if(Pos == string::npos)
		{
			if(Buffer.substr(Offset+1).length() > 2)
			{
				RequestLines.push_back(Buffer.substr(Offset-2, 2));
				RequestLines.push_back(Buffer.substr(Offset));
				break;
			}
			else
			{
				Buffer = "";
			}
		}
		else
		{
			RequestLines.push_back(Buffer.substr(Offset, (Pos - Offset)));

			if(RequestLines.back() == "")
			{
				RequestLines.pop_back();
			}

			Offset = Pos + 2;
		}
	}

	int ContentLength = -1;

	for(auto it = RequestLines.begin(); it != RequestLines.end(); ++it)
	{
		Pos = (*it).find(": ");
		if(Pos == string::npos)
		{
			// Blank line, therefore POST next
			if((*it) == "\r\n")
			{
				string PostData = "";
				for(auto it2 = (++it); it2 != RequestLines.end(); ++it2)
				{
					PostData += (*it2);
				}
				if(PostData.length() > 2)
				{
					mRequestInfo.mPostData = PostData.substr(2);
				}
				break;
			}
			// It's either invalid or POST data, later more likely
			//cout << "Received invalid HTTP Header, we may want to stop execution or we could just ignore." << endl;
		}
		else
		{
			mRequestInfo.mHeaders.push_back(pair<string, string>((*it).substr(0, Pos), (*it).substr(Pos + 2)));
			if(mRequestInfo.mHeaders.back().first == "Content-Length")
			{
				ContentLength = StrToStd<int>(mRequestInfo.mHeaders.back().second);
			}
		}
	}

	return true;
};
bool CHTTPRequest::PrepareResponse()
{
	mResponse = new CHTTPResponse;

	mResponse->mClient = mClient;
	mResponse->mRequestInfo = &mRequestInfo;
	
	return mResponse->PrepareResponse();
};
bool CHTTPRequest::DoResponse()
{
	
	return mResponse->ExecuteResponse();
};

bool CHTTPRequest::Output()
{
	return true;
};

bool CHTTPRequest::Die()
{
	//cout << endl;
	mResponse->CleanUp();

	// Cleaning up mClient and mResponse done by IRequest deconstructor

	return true;
};
